package com.sedsy.abc.baggetter;

import android.content.Context;

import com.ftdi.j2xx.D2xxManager;
import com.ftdi.j2xx.FT_Device;

import java.lang.ref.WeakReference;

/**
 * 售袋机管理器
 */
public class BagManager {
    D2xxManager manager;
    FT_Device ft_device;
    WeakReference<Context> context;
    volatile static BagManager bagManager;
    /**
     * 获取售袋机管理器实例
     *
     * @param context 上下文
     * @return 实例
     */
    public static BagManager getInstance(Context context){
        if(bagManager == null){
            synchronized (BagManager.class){
                if(bagManager == null){
                    bagManager = new BagManager(context);
                }
            }
        }
        return bagManager;
    }
    BagManager(Context context) {
        this.context = new WeakReference<>(context);
    }

    /**
     * 返回USB设备是否打开
     *
     * @return
     */
    public boolean isConnected(){
        if(ft_device!=null)
            return ft_device.isOpen();
        return false;
    }
    /**
     * 连接USB设备，默认连接第一个设备
     */
    public void connect(){
        try {
            manager = D2xxManager.getInstance(context.get());
            int size = manager.createDeviceInfoList(context.get());
            if(size>0){
                ft_device = manager.openByIndex(context.get(),0);
                ft_device.setBaudRate(115200);
                ft_device.setDataCharacteristics(D2xxManager.FT_DATA_BITS_8,D2xxManager.FT_STOP_BITS_1,D2xxManager.FT_PARITY_NONE);
            }
        } catch (D2xxManager.D2xxException e) {
            e.printStackTrace();
        }
    }

    /**
     * 断开已经连接的USB设备
     */
    public void disconnect(){
        if(ft_device!=null && ft_device.isOpen())
            ft_device.close();

    }
    boolean canSpitBag(){
        return ft_device!=null && (ft_device.isOpen() || manager.createDeviceInfoList(context.get())>0);
    }
    public enum BagSizeEnum{
        SmallBag,
        BigBag,
    }
    Result getMachineStatus(byte[] b_result){
        Result result = new Result();
        int code = b_result[5] & 0xff;
        result.setResultCode(code&0xff);
        switch (code){
            case 0x2:
                result.setResultDescription("大袋子售袋");
                break;
            case 0x1:
                result.setResultDescription("小袋子售袋");
                break;
            case 0x6:
                result.setResultDescription("大袋子箱开");
                break;
            case 0x5:
                result.setResultDescription("小袋子箱开");
                break;
            case 0x9:
                result.setResultDescription("小袋子缺袋");
                break;
            case 0xA:
                result.setResultDescription("大袋子缺袋");
                break;
            case 0x88:
                result.setResultDescription("该序号袋子已经出售过，不再重售袋子");
                break;
            case 0x0:
                result.setResultDescription("正在执行操作");
                break;
            case 0xb:
                result.setResultDescription("小袋子卡袋");
                break;
            case 0xc:
                result.setResultDescription("大袋子卡袋");
                break;
            case 0xF0:
                result.setResultDescription("无故障");
                break;
            default:
                result.setResultDescription("未知错误");
                break;
        }
        return result;
    }
    int lastId = 0;
    byte getCommandCode(BagSizeEnum bagSize){
        switch (bagSize){
            case SmallBag:
                return 0x1;
            case BigBag:
                return 0x2;
        }
        return 0;
    }

    /**
     * 售袋机出袋
     *
     * @param bagSize 购物袋大小
     * @return 处理结果
     * @throws Exception the exception
     */
    public Result spitBag(BagSizeEnum bagSize) throws Exception{
        Result result = new Result();
        if(!canSpitBag()){
            result.setResultCode(-1);
            result.setResultDescription("未找到设备或未连接设备");
            return result;
        }
        byte[] tmp = new byte[]{(byte)0xCF,(byte)0xF1,(byte)0x0,(byte)0x00,(byte)0x0,(byte)0x0,(byte)0x0,(byte)0x0};
        //设置序号
        tmp[2] = (byte)(lastId & 0xff);
        tmp[3] = (byte)((lastId++>>8) & 0xff);
        tmp[4] = getCommandCode(bagSize);
        tmp[5] = getCommandCode(bagSize);
        int sum = 0;
        for(int i = 0;i<6;i++)
            sum+=(tmp[i]&0xff);
        tmp[6] = (byte)(~sum & 0xff);
        tmp[7] = (byte)((~sum&0xff00)>>>8);
        ft_device.purge((byte)1);
        ft_device.write(tmp,8);
        byte[] receive = new byte[8];
        ft_device.read(receive,8,2000);
        do {
            receive = new byte[8];
            ft_device.read(receive,8,2000);
            sum = 0;
            for(int i = 0;i<6;i++)
                sum+=receive[i];
            if(receive[6] != (byte)(~sum & 0xff) || receive[7]!=(byte)(~sum&0xff00)>>>8)
            {
                ft_device.purge((byte)1);
                continue;
            }
            if(receive[5] == (0x88 & 0xff)){
                lastId += 8;
                tmp[3] = (byte)(lastId & 0xff);
                ft_device.write(tmp,8);
                continue;
            }
        }while(receive[0]==0);
        return getMachineStatus(receive);
    }
}
